#ifndef _EXCEPTION_H_
#define _EXCEPTION_H_

////////////////////////////////////////////////////////////////////////////////
// Includes
////////////////////////////////////////////////////////////////////////////////

// Base class
#include <exception>

// String
#include <string>

////////////////////////////////////////////////////////////////////////////////
// Namespaces
////////////////////////////////////////////////////////////////////////////////

namespace Exceptions {

////////////////////////////////////////////////////////////////////////////////
// Implementation
////////////////////////////////////////////////////////////////////////////////

/**
 *  Generic exception class.
 *	This class creates a generic exception.
 */
 
class Exception : public std::exception {

	public:

		/**
		 *  Exception creation.
		 *	@param A specific message.
		 */
		Exception(
			const std::string comment = "",
			const std::string type = "Exception"
		) throw() : exception()
		{
			this->comment = comment;
			this->type = type;
		}

		/// Create a copy of the given instance
		Exception(const Exception & inst) throw()
		: type(inst.type), comment(inst.comment) {}
		
		// Affectation operator
		Exception & operator =(const Exception & inst) throw() {
			if (this != &inst) {
				this->type = inst.type;
				this->comment = inst.comment;
			}
			return *this;
		}

		/**
		 *  Exception destruction.
		 */
		virtual ~Exception() throw() {}

		/**
		 *  Exception message
		 *	@return The message
		 */
		virtual const char* what() const throw() {
			return (this->type + " : " + this->comment).c_str();
		}
		
		/**
		 *  Exception message using string
		 *	@return The message
		 */
		virtual const std::string What() const throw() {
			return (this->type + " : " + this->comment);
		}
		
		/**
		 *  Exception type
		 *	@return The type
		 */
		virtual const std::string & Type() const throw() {
			return this->type;
		}
		
		/**
		 *  Exception comment
		 *	@return The comment
		 */
		virtual const std::string & Comment() const throw() {
			return this->comment;
		}
		
	protected:
		
		/// Exception type
		std::string type;
		
		/// Exception message
		std::string comment;

};

////////////////////////////////////////////////////////////////////////////////
// Closing Namespaces
////////////////////////////////////////////////////////////////////////////////

}

////////////////////////////////////////////////////////////////////////////////

#endif
